package com.ruoyi.basicsystem.service.impl;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import com.ruoyi.basicsystem.domain.*;
import com.ruoyi.basicsystem.mapper.ZnAccountHeadMapper;
import com.ruoyi.basicsystem.mapper.ZnAccountItemMapper;
import com.ruoyi.bill.domain.ZnDepotHead;
import com.ruoyi.bill.mapper.ZnDepotHeadMapper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;
import com.ruoyi.basicsystem.mapper.ZnAccountMapper;
import com.ruoyi.basicsystem.service.IZnAccountService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;

/**
 * 结算账号Service业务层处理
 * 
 * @author nexiaozi
 * @date 2022-02-21
 */
@Service
public class ZnAccountServiceImpl implements IZnAccountService 
{
    @Autowired
    private ZnAccountMapper znAccountMapper;
    @Autowired
    private ZnDepotHeadMapper znDepotHeadMapper;
    @Autowired
    private ZnAccountHeadMapper znAccountHeadMapper;
    @Autowired
    private ZnAccountItemMapper znAccountItemMapper;
    /**
     * 查询结算账号
     * 
     * @param id 结算账号主键
     * @return 结算账号
     */
    @Override
    public ZnAccount selectZnAccountById(Long id)
    {
        return znAccountMapper.selectZnAccountById(id);
    }

    /**
     * 查询结算账号列表
     * 
     * @param znAccount 结算账号
     * @return 结算账号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<ZnAccount> selectZnAccountList(ZnAccount znAccount) {
        znAccount.setTenantId(SecurityUtils.getTenantId());
        znAccount.setDeleteFlag("0");
        List<ZnAccount> list =  znAccountMapper.selectZnAccountList(znAccount);
        List<AccountVo4List> result = new ArrayList<>();
        try {

            String timeStr = DateUtils.getCurrentMonth();
            if (null != list && null !=timeStr) {
                for (ZnAccount al : list) {
                    DecimalFormat df = new DecimalFormat(".##");
//                    BigDecimal thisMonthAmount =getAccountSum(al.getId(), timeStr, "month").add(getAccountSumByHead(al.getId(), timeStr, "month")).add(getAccountSumByDetail(al.getId(), timeStr, "month")).add(getManyAccountSum(al.getId(), timeStr, "month"));
//                    String thisMonthAmountFmt = "0";
//                    if ((thisMonthAmount.compareTo(BigDecimal.ZERO))!=0) {
//                        thisMonthAmountFmt = df.format(thisMonthAmount);
//                    }
                    BigDecimal currentAmount = getAccountSum(al.getId(), "", "month").add(getAccountSumByHead(al.getId(), "", "month")).add(getAccountSumByDetail(al.getId(), "", "month")).add(getManyAccountSum(al.getId(), "", "month")) .add(al.getInitialAmount()) ;
                    al.setCurrentAmount(currentAmount);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
        return list;
    }
    /**
     * 查询结算账号列表
     *
     * @param znAccount 结算账号
     * @return 结算账号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<AccountVo4List> selectZnAccountVo4List(ZnAccount znAccount) {
        znAccount.setTenantId(SecurityUtils.getTenantId());
        znAccount.setDeleteFlag("0");
        List<ZnAccount> list =  znAccountMapper.selectZnAccountList(znAccount);
        List<AccountVo4List> result = new ArrayList<>();
        try {
            String timeStr = DateUtils.getCurrentMonth();
            if (null != list && null !=timeStr) {
                for (ZnAccount al : list) {
                    AccountVo4List acountVo4List=new AccountVo4List();
                    BeanUtil.copyProperties(al,acountVo4List);
                    DecimalFormat df = new DecimalFormat("0.##");
                    BigDecimal thisMonthAmount =getAccountSum(al.getId(), timeStr, "month").add(getAccountSumByHead(al.getId(), timeStr, "month")).add(getAccountSumByDetail(al.getId(), timeStr, "month")).add(getManyAccountSum(al.getId(), timeStr, "month"));
                    String thisMonthAmountFmt = "0.00";
                    if ((thisMonthAmount.compareTo(BigDecimal.ZERO))!=0) {
                        thisMonthAmountFmt = df.format(thisMonthAmount);
                    }
                    acountVo4List.setThisMonthAmount(thisMonthAmountFmt);  //本月发生额
                    BigDecimal currentAmount = getAccountSum(al.getId(), "", "month").add(getAccountSumByHead(al.getId(), "", "month")).add(getAccountSumByDetail(al.getId(), "", "month")).add(getManyAccountSum(al.getId(), "", "month")) .add(al.getInitialAmount()) ;
                    acountVo4List.setCurrentAmount(currentAmount);
                    result.add(acountVo4List);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
        return result;
    }

    @Override
    public List<AccountVo4InOutList> findAccountInOutList(Long accountId, Map<String,Object> paramMap) {

        List<AccountVo4InOutList> list=null;
        list = znAccountMapper.findAccountInOutList(accountId,SecurityUtils.getLoginUser().getUser().getTenantId(),paramMap.get("billNo") !=null?paramMap.get("billNo").toString():null,paramMap.get("operTimeBegin")!=null?paramMap.get("operTimeBegin").toString():null,paramMap.get("operTimeEnd")!=null?paramMap.get("operTimeEnd").toString():null,paramMap.get("type")!=null?paramMap.get("type").toString():null);

        return list;
    }

    /**
      * 查询结算账号记录数
      *
      * @param znAccount 结算账号
      * @return 结算账号记录数
     */
    public Integer selectZnAccountCount(ZnAccount znAccount){
        return znAccountMapper.selectZnAccountCount(znAccount);
    }


    /**
     * 新增结算账号
     * 
     * @param znAccount 结算账号
     * @return 结果
     */
    @Override
    public int insertZnAccount(ZnAccount znAccount)
    {
        znAccount.setDeleteFlag("0");
        znAccount.setTenantId(SecurityUtils.getTenantId());
        znAccount.setIsDefault(0);
        if(znAccount.getCurrentAmount() ==null){
            znAccount.setCurrentAmount(new BigDecimal(0));
        }
        if(znAccount.getInitialAmount()==null){
            znAccount.setInitialAmount(new BigDecimal(0));
        }
        return znAccountMapper.insertZnAccount(znAccount);
    }

    /**
     * 修改结算账号
     * 
     * @param znAccount 结算账号
     * @return 结果
     */
    @Override
    public int updateZnAccount(ZnAccount znAccount)
    {
        return znAccountMapper.updateZnAccount(znAccount);
    }

    /**
     * 批量删除结算账号
     * 
     * @param ids 需要删除的结算账号主键
     * @return 结果
     */
    @Override
    public int deleteZnAccountByIds(Long[] ids)
    {
        return znAccountMapper.deleteZnAccountByIds(ids);
    }

    /**
     * 删除结算账号信息
     * 
     * @param id 结算账号主键
     * @return 结果
     */
    @Override
    public int deleteZnAccountById(Long id)
    {
        return znAccountMapper.deleteZnAccountById(id);
    }
    /**
     * 设置为默认结算账号
     *
     * @param id 结算账号主键
     * @return 结果
     */
    @Override
    @Transactional
    public int setDefault(Long id) {
        ZnAccount znAccount = new ZnAccount();
        znAccount.setId(id);
        znAccount.setTenantId(SecurityUtils.getTenantId());
        return  znAccountMapper.setDefault(znAccount);
    }

    @Override
    public Map<String, Object> getStatistics(ZnAccount znAccount) {

        Map<String, Object> map = new HashMap<>();
        try {
            znAccount.setTenantId(SecurityUtils.getTenantId());
            List<ZnAccount> list = getAccountByParam(znAccount);
            String timeStr =new SimpleDateFormat("yyyy-MM").format(new Date());//获取当前月 yyyy-MM
            BigDecimal allMonthAmount = BigDecimal.ZERO;
            BigDecimal allCurrentAmount = BigDecimal.ZERO;
            if (null != list && null !=timeStr) {
                for (ZnAccount a : list) {
                    BigDecimal monthAmount = getAccountSum(a.getId(), timeStr, "month").add(getAccountSumByHead(a.getId(), timeStr, "month"))
                            .add(getAccountSumByDetail(a.getId(), timeStr, "month")).add(getManyAccountSum(a.getId(), timeStr, "month"));
                  /*  BigDecimal aaa=getAccountSum(a.getId(), "", "month");
                    BigDecimal bbb=getAccountSumByHead(a.getId(), "", "month");
                    BigDecimal ccc=getAccountSumByDetail(a.getId(), "", "month");
                    BigDecimal ddd=getManyAccountSum(a.getId(), "", "month");
                    System.out.printf(aaa+"/n");
                    System.out.printf(bbb+"/n");
                    System.out.printf(ccc+"/n");
                    System.out.printf(ddd+"/n");*/
                    BigDecimal currentAmount = getAccountSum(a.getId(), "", "month").add(getAccountSumByHead(a.getId(), "", "month"))
                            .add(getAccountSumByDetail(a.getId(), "", "month")).add(getManyAccountSum(a.getId(), "", "month")).add(a.getInitialAmount());
                    allMonthAmount = allMonthAmount.add(monthAmount);
                    allCurrentAmount = allCurrentAmount.add(currentAmount);
                }
            }
            map.put("allCurrentAmount", priceFormat(allCurrentAmount));  //当前总金额
            map.put("allMonthAmount", priceFormat(allMonthAmount));  //本月发生额
        } catch (Exception e) {
         e.printStackTrace();
        }
        return map;
    }



    public List<ZnAccount> getAccountByParam(ZnAccount znAccount) throws Exception{
        znAccount.setTenantId(SecurityUtils.getTenantId());
        List<ZnAccount> list=znAccountMapper.getAccountByParam(znAccount);

        return list;
    }
    /**
     * 单个账户的金额求和-入库和出库
     *
     * @param id
     * @return
     */
    @Override
    public BigDecimal getAccountSum(Long id, String timeStr, String type) throws Exception{
        BigDecimal accountSum = BigDecimal.ZERO;
        try{
            Map<String, Object> params=new HashMap<>();
            if (!timeStr.equals("")) {
                Date bTime = StringUtil.getDateByString(DateUtils.firstDayOfMonth(timeStr) + DateUtils.DAY_FIRST_TIME, null);
                Date eTime = StringUtil.getDateByString(DateUtils.lastDayOfMonth(timeStr) + DateUtils.DAY_LAST_TIME, null);
                Date mTime = StringUtil.getDateByString(DateUtils.firstDayOfMonth(timeStr) + DateUtils.DAY_FIRST_TIME, null);
                if (type.equals("month")) {
                    params.put("beginOperTime",bTime);
                    params.put("endOperTime",eTime);

                } else if (type.equals("date")) {
                    params.put("endOperTime",mTime);
                }
            }
            params.put("otherParams"," pay_type !='预付款'");
            List<ZnDepotHead> dataList=null;
                ZnDepotHead znDepotHeadQuery=new ZnDepotHead();
                znDepotHeadQuery.setAccountId(id);
                znDepotHeadQuery.setTenantId(SecurityUtils.getLoginUser().getUser().getTenantId());

        znDepotHeadQuery.setParams(params);
                dataList = znDepotHeadMapper.selectZnDepotHeadByDate(znDepotHeadQuery);

            if (dataList != null) {
                for (ZnDepotHead depotHead : dataList) {
                    if(depotHead.getChangeAmount()!=null) {
                        accountSum = accountSum .add(depotHead.getChangeAmount()) ;
                    }
                }
            }
        } catch (DataAccessException e) {
            e.printStackTrace();
        }
        if(accountSum==null){
            System.out.printf(accountSum+"");
        }
        return accountSum;
    }

    /**
     * 单个账户的金额求和-收入、支出、转账的单据表头的合计
     *
     * @param id
     * @return
     */
    public BigDecimal getAccountSumByHead(Long id, String timeStr, String type) throws Exception{
        BigDecimal accountSum = BigDecimal.ZERO;
try
{
            Map<String, Object> params=new HashMap<>();
            if (!timeStr.equals("")) {
                Date bTime = StringUtil.getDateByString(DateUtils.firstDayOfMonth(timeStr) + DateUtils.DAY_FIRST_TIME, null);
                Date eTime = StringUtil.getDateByString(DateUtils.lastDayOfMonth(timeStr) + DateUtils.DAY_LAST_TIME, null);
                Date mTime = StringUtil.getDateByString(DateUtils.firstDayOfMonth(timeStr) + DateUtils.DAY_FIRST_TIME, null);
                if (type.equals("month")) {
                    params.put("beginBillTime",bTime);
                    params.put("endBillTime",eTime);

                } else if (type.equals("date")) {
                    params.put("endBillTime",mTime);
                }
            }
            List<ZnAccountHead> dataList=null;
                ZnAccountHead znAccountHeadQuery=new ZnAccountHead();
    znAccountHeadQuery.setAccountId(id);
    znAccountHeadQuery.setTenantId(SecurityUtils.getLoginUser().getUser().getTenantId());
        znAccountHeadQuery.setParams(params);
                dataList = znAccountHeadMapper.selectZnAccountHeadByDate(znAccountHeadQuery);

            if (dataList != null) {
                for (ZnAccountHead accountHead : dataList) {
                    if(accountHead.getChangeAmount()!=null) {
                        accountSum = accountSum.add(accountHead.getChangeAmount());
                    }
                }
            }
    } catch (DataAccessException e) {
    e.printStackTrace();
}
        return accountSum;
    }

    /**
     * 单个账户的金额求和-收款、付款、转账、收预付款的单据明细的合计
     *
     * @param id
     * @return
     */
    @Override
    public BigDecimal getAccountSumByDetail(Long id, String timeStr, String type)throws Exception {
        BigDecimal accountSum =BigDecimal.ZERO ;
        try{
            Map<String, Object> params=new HashMap<>();
            if (!timeStr.equals("")) {
                Date bTime = StringUtil.getDateByString(DateUtils.firstDayOfMonth(timeStr) + DateUtils.DAY_FIRST_TIME, null);
                Date eTime = StringUtil.getDateByString(DateUtils.lastDayOfMonth(timeStr) + DateUtils.DAY_LAST_TIME, null);
                Date mTime = StringUtil.getDateByString(DateUtils.firstDayOfMonth(timeStr) + DateUtils.DAY_FIRST_TIME, null);
                if (type.equals("month")) {
                    params.put("beginBillTime",bTime);
                    params.put("endBillTime",eTime);

                } else if (type.equals("date")) {
                    params.put("endBillTime",mTime);
                }
            }
            List<ZnAccountHead> dataList=null;
            ZnAccountHead znAccountHeadQuery=new ZnAccountHead();
            znAccountHeadQuery.setParams(params);
//            znAccountHeadQuery.setAccountId(id);
            znAccountHeadQuery.setTenantId(SecurityUtils.getLoginUser().getUser().getTenantId());
            dataList = znAccountHeadMapper.selectZnAccountHeadByDate(znAccountHeadQuery);
            if (dataList != null) {
                String ids = "";
                for (ZnAccountHead accountHead : dataList) {
                    ids = ids + accountHead.getId() + ",";
                }
                if (!ids.equals("")) {
                    ids = ids.substring(0, ids.length() - 1);
                }


                if (!ids.equals("")) {
                    List<Long> idList = StringUtil.strToLongList(ids);
                   /* exampleAi.createCriteria().andAccountIdEqualTo(id).andHeaderIdIn(idList)
                            .andDeleteFlagNotEqualTo(BusinessConstants.DELETE_FLAG_DELETED);*/
                    List<ZnAccountItem> dataListOne = znAccountItemMapper.selectZnAccountItemListByAccHeadId(id,idList);
                    if (dataListOne != null) {
                        for (ZnAccountItem accountItem : dataListOne) {
                            if(accountItem.getEachAmount()!=null) {
                                accountSum = accountSum.add(accountItem.getEachAmount());
                            }
                        }
                    }
                }
            }
    } catch (DataAccessException e) {
        e.printStackTrace();
    }
        if(accountSum==null){
            System.out.printf(accountSum+"");
        }
        return accountSum;
    }
    /**
     * 单个账户的金额求和-多账户的明细合计
     *
     * @param id
     * @return
     */
    @Override
    public BigDecimal getManyAccountSum(Long id, String timeStr, String type)throws Exception {
        BigDecimal accountSum = BigDecimal.ZERO;
        try {
            Map<String, Object> params=new HashMap<>();
            if (!timeStr.equals("")) {
                Date bTime = StringUtil.getDateByString(DateUtils.firstDayOfMonth(timeStr) + DateUtils.DAY_FIRST_TIME, null);
                Date eTime = StringUtil.getDateByString(DateUtils.lastDayOfMonth(timeStr) + DateUtils.DAY_LAST_TIME, null);
                Date mTime = StringUtil.getDateByString(DateUtils.firstDayOfMonth(timeStr) + DateUtils.DAY_FIRST_TIME, null);
                if (type.equals("month")) {
                    params.put("beginOperTime",bTime);
                    params.put("endOperTime",eTime);

                } else if (type.equals("date")) {
                    params.put("endOperTime",mTime);
                }
            }
            params.put("accountIdList",id);
            ZnDepotHead znDepotHeadQuery=new ZnDepotHead();
            znDepotHeadQuery.setTenantId(SecurityUtils.getLoginUser().getUser().getTenantId());
            znDepotHeadQuery.setParams(params);
            List<ZnDepotHead> dataList=null;
                dataList = znDepotHeadMapper.selectZnDepotHeadByDate(znDepotHeadQuery);

            if (dataList != null) {
                for (ZnDepotHead depotHead : dataList) {
                    String accountIdList = depotHead.getAccountIdList();
                    String accountMoneyList = depotHead.getAccountMoneyList();
                    if(StringUtil.isNotEmpty(accountIdList) && StringUtil.isNotEmpty(accountMoneyList)) {
                        accountIdList = accountIdList.replace("[", "").replace("]", "").replace("\"", "");
                        accountMoneyList = accountMoneyList.replace("[", "").replace("]", "").replace("\"", "");
                        String[] aList = accountIdList.split(",");
                        String[] amList = accountMoneyList.split(",");
                        for (int i = 0; i < aList.length; i++) {
                            if (aList[i].toString().equals(id.toString())) {
                                if(amList!=null && amList.length>0) {
                                    accountSum = accountSum.add(new BigDecimal(amList[i]));
                                }
                            }
                        }
                    }
                }
            }
        } catch (DataAccessException e) {
          e.printStackTrace();
        }
        return accountSum;
    }

    @Override
    public List<AccountVo4InOutList> findAccountInOutList(Long accountId) {
        List<AccountVo4InOutList> list=null;
            list = znAccountMapper.findAccountInOutList(accountId,SecurityUtils.getLoginUser().getUser().getTenantId());

        return list;
    }

    @Override
    public Map<Long, String> getAccountMap() {
        ZnAccount znAccount=new ZnAccount();
        znAccount.setDeleteFlag("0");
        List<ZnAccount> accountList = selectZnAccountList(znAccount);
        Map<Long,String> accountMap = new HashMap<>();
        for(ZnAccount account : accountList){
            accountMap.put(account.getId(), account.getName());
        }
        return accountMap;
    }

    @Override
    public String getAccountStrByIdAndMoney(Map<Long, String> accountMap, String accountIdList, String accountMoneyList) {
        StringBuffer sb = new StringBuffer();
        List<Long> idList = StringUtil.strToLongList(accountIdList);
        List<Long> moneyList = StringUtil.strToLongList(accountMoneyList);
        for (int i = 0; i < idList.size(); i++) {
            Long id = idList.get(i);
            BigDecimal money =  BigDecimal.valueOf(moneyList.get(i)).abs();
            sb.append(accountMap.get(id) + "(" + money + "元) ");
        }
        return sb.toString();
    }

    @Override
    public AccountHeadVo4ListEx selectZnAccountDetailByBillNo(String billNo) {
        List<AccountHeadVo4ListEx> list = znAccountHeadMapper.getDetailByNumber(billNo);
        AccountHeadVo4ListEx result = null;
        if(list !=null && list.size()>0){
            result = list.get(0);
        }
        return result;
    }

    /**
     * 价格格式化
     * @param price
     * @return
     */
    private String priceFormat(BigDecimal price) {
        String priceFmt = "0";
        DecimalFormat df = new DecimalFormat(".##");
        if ((price.compareTo(BigDecimal.ZERO))!=0) {
            priceFmt = df.format(price);
        }
        return priceFmt;
    }
}
